#include "sql_mcrecorder.h"
#include <QDateTime>
#include <sys/time.h>
#include <QtConcurrent>
#include <QScreen>
#include <QGuiApplication>

Sql_MCRecorder::Sql_MCRecorder(Sql_MCDefine *i_sql_mcdefine)
{
    //建立和sqlite数据的连接
    db = QSqlDatabase::addDatabase("QSQLITE",QString("excmcrecorder"));
    //设置数据库文件的名字
    db.setDatabaseName(QString("../EXC_SQL/EXC_MC_RECORDER.db"));

    sql_mcdefine = i_sql_mcdefine;

    //缓存modbus数据寄存器
    m_constantRecorder.insert(0, 0x71,0x0);
    m_regulatorRecorderA.insert(0, 0xEC,0x0);
    m_regulatorRecorderB.insert(0, 0xEC,0x0);
    m_regulatorRecorderTime.insert(0, 0x6,0x0);
    m_flagConstantRecorder = false;

    //保存用户权限状态
    m_operatorMode = 90;

    //一直录波(default):3
    //警报存在时录波:2
    //新警报到达时录波十分钟:4
    m_dataFEnableFlag = false;
    m_dataFWriteFlag = false;
    m_recordWave = 2;
    m_dataFCounter = 0;

    m_recordTWave=0;

    //打开数据库
    OpenDb();
    //清空alarm_now表
    qml_queryTableOne(tr("delete from alarm_now"));
    //对时
//    m_timeSynFlag = qml_getTimeSynFlag();

    //qml打印功能
#ifdef _QML_DEBUG_PRINT_
    qml_printFlag = true;
#else
    qml_printFlag = false;
#endif

    //qml非焦点不刷新功能
#ifdef _QML_FOCUS_REFURBISH_
    qml_refurbishFlag = true;
#else
    qml_refurbishFlag = false;
#endif

//    this->start();
}

Sql_MCRecorder::~Sql_MCRecorder()
{
    CloseDb();
}

bool Sql_MCRecorder::OpenDb()
{
    //打开数据库
    if(!db.open()){
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "连接record数据失败！";
#endif
        return false;
    }
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "连接record数据库成功";
#endif
    return true;
}

void Sql_MCRecorder::CloseDb()
{
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "record数据库close";
#endif
    db.close();
}


//********************* 传入语句查询 **********************
//*********** 执行一个语句，只返回第一个参数
//i_str:SQL语句
QJsonValue Sql_MCRecorder::qml_queryTableOne(QString i_str)
{
    QSqlQuery query(db);
    //执行sql语句,并将结果集保存到model
    if(query.exec(i_str)==false){
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "执行数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
                 << "SQL错误:表达式错误";
#endif
        return QJsonValue(QString("NULL"));
    }
    if(query.next()){
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "执行数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
                 << "SQL结果" << query.value(0).toString();
#endif
        return QJsonValue(query.value(0).toString());
    }
    else{
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "执行数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
                 << "no result";
#endif
        return "NULL";
    }
}

//*********** 查询和显示结果-qml接口，多行R、单列C
//i_str:SQL语句
QVector<QString> Sql_MCRecorder::qml_queryTable1RnCRetVec(QString i_str)
{
    QVector<QString> t_vec;
    QSqlQuery query(db);
    //执行sql语句,并将结果集保存到model
    if(query.exec(i_str)==false){
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
                 << "SQL错误::表达式错误";
#endif
        return t_vec;
    }
    if(query.next()){
        for(int t_counter=0; (query.value(t_counter).toString()!=NULL); t_counter++){
            t_vec.push_back(query.value(t_counter).toString());
        }
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
                 << "SQL结果" << t_vec;
#endif
    }
    else
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
                 << "no result";
#endif
    return t_vec;
}

//*********** 查询和显示结果-qml接口，单行R、多列C
//i_str:SQL语句
QVector<QString> Sql_MCRecorder::qml_queryTablenR1CRetVec(QString i_str)
{
    QVector<QString> t_vec;
    QSqlQuery query(db);
    //执行sql语句,并将结果集保存到model
    if(query.exec(i_str)==false){
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
                 << "SQL错误::表达式错误";
#endif
        return t_vec;
    }
    while(query.next())
    {
        t_vec.push_back(query.value(0).toString());
    }
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
             << " SQL结果:" << t_vec;
#endif
    return t_vec;
}

//*********** 查询和显示结果-qml接口，多行R，多列C
//i_str:SQL语句
//返回值:vector形式返回，通过qml_getVecResult2D获取返回值
bool Sql_MCRecorder::qml_queryTable2DRetBool(QString i_str)
{
    QSqlQuery query(db);
    o_queryResult2D.clear();
    //执行sql语句,并将结果集保存到model
    if(query.exec(i_str)==false){
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
                 << "SQL错误:表达式错误";
#endif
        return false;
    }
    while(query.next())
    {
        QVector<QString> t_qverQstring;
        for(int t_counter=0; (query.value(t_counter).toString()!=NULL); t_counter++){
//            qDebug() << query.value(t_counter);
            t_qverQstring.push_back(query.value(t_counter).toString());
        }
        o_queryResult2D.push_back(t_qverQstring);
    }
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
             << "SQL结果" << o_queryResult2D;
#endif
    return true;
}

//function:返回qml_queryTable2D得到的数据
//i:第几行
QVector<QString> Sql_MCRecorder::qml_getVecResult2D(unsigned int i)
{
    return o_queryResult2D[i];
}

//function:返回qml_queryTable2D得到的数据个数
int Sql_MCRecorder::qml_getVecResult2DNum()
{
    return o_queryResult2D.size();
}

//function:查询完直接返回 2D 容器数组
QVector<QVector<QString>> Sql_MCRecorder::qml_queryTable2DRetVec2D(QString i_str)
{
    QVector<QVector<QString>> t_retVal;
    QSqlQuery query(db);
    //执行sql语句,并将结果集保存到model
    if(query.exec(i_str)==false){
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
                 << "SQL错误:表达式错误";
#endif
        return t_retVal;
    }
    while(query.next())
    {
        QVector<QString> t_qverQstring;
        for(int t_counter=0; (query.value(t_counter).toString()!=NULL); t_counter++){
            t_qverQstring.push_back(query.value(t_counter).toString());
        }
        t_retVal.push_back(t_qverQstring);
    }
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
             << "SQL结果:2D，第一个是:" << t_retVal;
#endif
    return t_retVal;
}

//function:查询完折叠成 1D 容器数组返回
QVector<QString> Sql_MCRecorder::qml_queryTable2DRetVec1D(QString i_str)
{
    QVector<QString> t_retVal;
    QSqlQuery query(db);
    //执行sql语句,并将结果集保存到model
    if(query.exec(i_str)==false){
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
                 << "SQL错误:表达式错误";
#endif
        return t_retVal;
    }
    while(query.next())
    {
        for(int t_counter=0; (query.value(t_counter).toString()!=NULL); t_counter++){
            t_retVal.push_back(query.value(t_counter).toString());
        }
    }
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "查询数据库EXC_MC_RECORDER 表recorder SQL语句:" << i_str
             << "SQL结果:2D，第一个是:" << t_retVal;
#endif
    return t_retVal;
}

//********************* 特殊查询 **********************
//function:执行特定语句，查询recorder某个dec的value的某个位
//return:bool，若没有则返回-1
bool Sql_MCRecorder::qml_getBitBool(QString i_prefixion, QString i_tableName, QString i_function)
{
    //1-
    QVector<int> t_dec, t_bit;
    if(sql_mcdefine->cpp_getBitDec(i_prefixion, i_tableName, i_function, t_dec, t_bit)<=0)
    {
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "BOOL判断结果:传入参数出错";
#endif
        return 0;
    }
    //2-
    if(qml_getRecordVal_touint16(t_dec[0])&(1<<t_bit[0]))
    {
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "BOOL判断结果:true";
#endif
        return 1;
    }
    else
    {
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "BOOL判断结果:false";
#endif
        return 0;
    }
}

int Sql_MCRecorder::qml_queryTableItemNum(QString i_tableName)
{
    QSqlQuery query(db);
    //执行sql语句,并将结果集保存到model
    if(query.exec(QString("SELECT COUNT(*) FROM %1").arg(i_tableName))==false){
#ifdef _SQL_DEBUG_PRINT_
        qDebug() << "查询数据库EXC_MC_RECORDER 表"<< i_tableName << " SQL语句:" << QString("SELECT COUNT(*) FROM %1").arg(i_tableName)
                 << "SQL结果:query error";
#endif
        return 0;
    }
    query.next();
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "查询数据库EXC_MC_RECORDER 表表"<< i_tableName << " SQL语句:" << QString("SELECT COUNT(*) FROM %1").arg(i_tableName)
             << "SQL结果:" << QString(query.value(0).toString());
#endif
    return  query.value(0).toInt();
}

void Sql_MCRecorder::qml_setMotorFactor(QString i_str, int value)
{
    qml_queryTableOne(QString("UPDATE motor_factor SET value=%2 WHERE name='%1'").arg(i_str).arg(QString::number(value)));
}

QJsonValue Sql_MCRecorder::qml_getFactor(QString i_str)
{
    return qml_queryTableOne(QString("SELECT value FROM motor_factor WHERE name='%1'").arg(i_str));
}

//********************* 查询内存中MC参数 **********************
//function:执行特定语句，查询recorder某个dec的value
//return:int
int Sql_MCRecorder::qml_getRecordVal_toint16(int i_dec)
{
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "查询内存内寄存器数据 int:\t" << i_dec << "\t" << ((short)m_constantRecorder.at(i_dec-0x63)&0xFFFF);
#endif
    return (short)m_constantRecorder.at(i_dec-0x63);
}

//function:执行特定语句，查询recorder某个dec的value
//return:uint
unsigned int Sql_MCRecorder::qml_getRecordVal_touint16(int i_dec)
{
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "查询内存内寄存器数据 uint:\t" << i_dec << "\t0x" << QString::number((unsigned short)m_constantRecorder.at(i_dec-0x63)&0xFFFF,16);
#endif
    return (unsigned short)m_constantRecorder.at(i_dec-0x63)&0xFFFF;
}


//********************* 查询内存中调节器参数 **********************
int Sql_MCRecorder::qml_getRegulatorVal_toint16(int i_dec)
{
    int t_decChange = 0;
    short t_returnVal = 0;
    if(i_dec>=0x63 && i_dec<=0xD3)
    {
        t_decChange = 0x63;
        t_returnVal = (short)m_constantRecorder.at(i_dec-t_decChange)&0xFFFF;
    }
    else if(i_dec>=0x4101 && i_dec<=0x41EC)
    {
        t_decChange = 0x4101;
        t_returnVal = (short)m_regulatorRecorderA.at(i_dec-t_decChange)&0xFFFF;
    }
    else if(i_dec>=0x5101 && i_dec<=0x51EC)
    {
        t_decChange = 0x5101;
        t_returnVal = (short)m_regulatorRecorderB.at(i_dec-t_decChange)&0xFFFF;
    }
    else if(i_dec>=0x48f0 && i_dec<=0x48f5)
    {
        t_decChange = 0x48f0;
        t_returnVal = (short)m_regulatorRecorderTime.at(i_dec-t_decChange)&0xFFFF;
    }
    else return 0;
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "查询内存内调节器数据 uint:\t" << i_dec << "\t0x"
             << QString::number(t_returnVal,16);
#endif
    return t_returnVal;
}

unsigned int Sql_MCRecorder::qml_getRegulatorVal_touint16(int i_dec)
{
    int t_decChange = 0;
    unsigned short t_returnVal = 0;
    if(i_dec>=0x63 && i_dec<=0xD3)
    {
        t_decChange = 0x63;
        t_returnVal = (unsigned short)m_constantRecorder.at(i_dec-t_decChange)&0xFFFF;
    }
    else if(i_dec>=0x4101 && i_dec<=0x41EC)
    {
        t_decChange = 0x4101;
        t_returnVal = (unsigned short)m_regulatorRecorderA.at(i_dec-t_decChange)&0xFFFF;
    }
    else if(i_dec>=0x5101 && i_dec<=0x51EC)
    {
        t_decChange = 0x5101;
        t_returnVal = (unsigned short)m_regulatorRecorderB.at(i_dec-t_decChange)&0xFFFF;
    }
    else if(i_dec>=0x48f0 && i_dec<=0x48f5)
    {
        t_decChange = 0x48f0;
        t_returnVal = (unsigned short)m_regulatorRecorderTime.at(i_dec-t_decChange)&0xFFFF;
    }
    else return 0;
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "查询内存内调节器数据 uint:\t" << i_dec << "\t0x"
             << QString::number(t_returnVal,16);
#endif
    return t_returnVal;
}


//********************* 报警状态处理 **********************
//function:更新报警信息，并返回新增警报数量
int Sql_MCRecorder::qml_updateAlarmAndRetNum()
{
    QVector<QVector<QVariant>> t_vec;
    QVector<QString> t_alarmNowSendVec, t_alarmHisotrySendVec;
    sql_mcdefine->cpp_queryTable2D("SELECT dec,define,explicate,reg FROM mc_define WHERE define LIKE '%故障%'", t_vec);
    //1-遍历一次，如果格式不对不执行
    for(int i=0;i<t_vec.size();i++)
    {
        if(t_vec[i].size()!=4)
            return 0;
    }
    //2-查询表recorder得到每个dec对应的value,得到现在实时警报数据
    QVector<struct _QuerySetBitContent> t_newVerQc;
    for(int i=0;i<t_vec.size();i++)
    {
        unsigned int t_value = qml_getRecordVal_touint16(t_vec[i][0].toInt());
        for(int j=0; j<16; j++){
            if(t_value&(1<<j)){
                struct _QuerySetBitContent t_querySetBitContent={
                    .dec=t_vec.at(i).at(0).toInt(),
                            .bit=j,
                            .define=t_vec.at(i).at(1).toString(),
                            .explicate=t_vec.at(i).at(2).toString(),
                            .reg=t_vec.at(i).at(3).toString(),
                            .content=sql_mcdefine->cpp_queryTableOne(QString("SELECT function FROM %1 WHERE bit=%2 AND reg='%3'")
                                                                     .arg(t_vec.at(i).at(2).toString())
                                                                     .arg(j)
                                                                     .arg(t_vec[i][3].toString())).toString(),
                            .sorn=true
                };
                t_newVerQc.push_back(t_querySetBitContent);
            }
        }
    }
    //3-写入alarm_now
    //3.1-获取上一次（旧的）alarm_now的dec、bit、date、time、content；得到上一次（旧的）实时警报数据，因为新的警报还没写入数据库，数据库里面是上一次的
    QSqlQuery query(db);
    QVector<_QuerySetBitContentSimple> t_previousVerQcs;
    if(query.exec("SELECT dec,bit,data,time,content FROM alarm_now")==false){
#ifdef _CPP_DEBUG_PRINT_
        qDebug() << "error";
#endif
        return 0;
    }
#ifdef _SQL_DEBUG_PRINT_
    qDebug() << "查询数据库EXC_MC_RECORDER SQL语句:" << "SELECT dec,bit FROM alarm_now"
             << "SQL结果" << query.value(0);
#endif
    while(query.next())
    {
        struct _QuerySetBitContentSimple t_qcs{query.value(0).toInt(), query.value(1).toInt(), false,
                    query.value(2).toDate(), query.value(3).toTime(), query.value(4).toString()};
        t_previousVerQcs.push_back(t_qcs);
    }


    //3.2-对比t_newVerQc和t_previousVerQcs中的dec+bit
    //3.2.1-
    //默认t_newVerQc的sorn为true，t_previousVerQcs的sorn为false
    //重复则t_newVerQc和t_previousVerQcs的sorn翻转
    //t_newVerQc.sorn==false,新错误不会新增入alarm_now；写入alarm_history（产生）
    //t_previousVerQcs.sorn==false,旧错误会被删掉（复归了）；写入alarm_history（复归）

    //3.2.2-旧警报，仍然没有复归
    struct _RecordPreButStillSet{
        QDate date;
        QTime time;
        QString str;
    };
    QVector <struct _RecordPreButStillSet> t_recordPreButStillSet;

    for(int ab=0; ab<t_previousVerQcs.size(); ab++)
        for(int aa=0; aa<t_newVerQc.size(); aa++)
            if(t_newVerQc.at(aa).dec==t_previousVerQcs.at(ab).dec
                    && t_newVerQc.at(aa).bit==t_previousVerQcs.at(ab).bit)
            {
                t_newVerQc[aa].sorn=false;
                t_previousVerQcs[ab].sorn = true;
                //这个是上次已经存在，这次还有的警报，不能使用新的时间，从 t_previousVerQcs 里面获取
                struct _RecordPreButStillSet t={t_previousVerQcs[ab].date, t_previousVerQcs[ab].time, t_previousVerQcs[ab].str};
                t_recordPreButStillSet.push_back(t);
            }

    //3.3-获取现在时间
    QDateTime current_date_time =QDateTime::currentDateTime();
    QString current_date =current_date_time.toString("yyyy-MM-dd");
    QString current_time =current_date_time.toString("hh:mm:ss.zzz");

    //3.4-删掉alarm_now已经复归的项目；即t_previousVerQcs.sorn=false
    for(int i=0; i<t_previousVerQcs.size(); i++)
    {
        if(t_previousVerQcs.at(i).sorn == false){
            QJsonValue t_js = qml_queryTableOne(QString("SELECT content FROM alarm_now WHERE dec=%1 AND bit=%2")
                              .arg(t_previousVerQcs.at(i).dec)
                              .arg(t_previousVerQcs.at(i).bit));

            t_alarmHisotrySendVec.push_back(current_date);
            t_alarmHisotrySendVec.push_back(current_time);
            t_alarmHisotrySendVec.push_back(t_js.toString());
            t_alarmHisotrySendVec.push_back("false");

            qml_queryTableOne(QString("INSERT INTO alarm_history select dec,bit,'%1','%2','%3',content from alarm_now where dec=%4 AND bit=%5")
                              .arg(current_date).arg(current_time).arg("false")
                              .arg(QString::number(t_previousVerQcs.at(i).dec))
                              .arg(QString::number(t_previousVerQcs.at(i).bit)));
            qml_queryTableOne(QString("DELETE FROM alarm_now WHERE dec=%1 AND bit=%2" )
                              .arg(QString::number(t_previousVerQcs.at(i).dec))
                              .arg(QString::number(t_previousVerQcs.at(i).bit)));
        }
    }

    int t_retVal=0;
    //3.5-添加新错误；即t_newVerQc.sorn=true
    //alarm now中旧的警报放上面,新旧警报重复部分，用结构体 t_recordPreButStillSet 处理
    for(int i=0;i<t_recordPreButStillSet.size();i++)
    {
        t_alarmNowSendVec.push_back(t_recordPreButStillSet.at(i).date.toString("yyyy-MM-dd"));
        t_alarmNowSendVec.push_back(t_recordPreButStillSet.at(i).time.toString("hh:mm:ss.zzz"));
        t_alarmNowSendVec.push_back(t_recordPreButStillSet.at(i).str);
    }
    for(int i=0;i<t_newVerQc.size();i++)
    {
        if(t_newVerQc.at(i).sorn == true){
            qml_queryTableOne(QString("INSERT INTO alarm_now (dec,bit,data,time,content) VALUES (%1, %2, '%3', '%4', '%5')")
                              .arg(t_newVerQc.at(i).dec).arg(t_newVerQc.at(i).bit)
                              .arg(current_date).arg(current_time)
                              .arg(t_newVerQc.at(i).define+":"+t_newVerQc.at(i).content));
            qml_queryTableOne(QString("INSERT INTO alarm_history(dec,bit,data,time,setorreset,content) VALUES (%1,%2,'%3','%4','%5','%6')")
                              .arg(t_newVerQc.at(i).dec).arg(t_newVerQc.at(i).bit)
                              .arg(current_date).arg(current_time)
                              .arg("true")
                              .arg(t_newVerQc.at(i).define+":"+t_newVerQc.at(i).content));
            t_retVal++;
            t_alarmNowSendVec.push_back(current_date);
            t_alarmNowSendVec.push_back(current_time);
            t_alarmNowSendVec.push_back(t_newVerQc.at(i).define+":"+t_newVerQc.at(i).content);
            t_alarmHisotrySendVec.push_back(current_date);
            t_alarmHisotrySendVec.push_back(current_time);
            t_alarmHisotrySendVec.push_back(t_newVerQc.at(i).define+":"+t_newVerQc.at(i).content);
            t_alarmHisotrySendVec.push_back("true");
        }
    }

    //3.6-发送要更新的信息过去QML；如果history都没有要更新的，now更加没有需要更新的，就不用发送了，减少处理器压力
    if(t_alarmHisotrySendVec.size()!=0)
        sn_sqlAlarmWriteFinish(t_alarmNowSendVec, t_alarmHisotrySendVec);

//    if(t_alarmHisotrySendVec.size()!=0)
//        for(int i=0;i*3+2<t_alarmNowSendVec.size();i+=3)
//        {
//            qDebug() << QString("新增报警  时间 %1-%2 内容: %3")
//                        .arg(t_alarmNowSendVec.at(i)).arg(t_alarmNowSendVec.at(i+1))
//                        .arg(t_alarmNowSendVec.at(i+2));
//        }

    //3.7-启动警报录波
//    if(t_newVerQc.size()!=0 && m_recordWave==2) {m_recordWaveAlarmMode->start(600);m_dataFEnableFlag=true;/*qDebug() << "警报存在时录波启动一次";*/}
    if(t_retVal!=0 && m_recordWave==2) {m_dataFEnableFlag=true;m_dataFCounter = 0;qDebug() << "新警报到达时录波启动一次";}

    return t_retVal;
}


void Sql_MCRecorder::qml_updateAlarmAndSendMsg()
{
    SL_updateAlarmAndSendMsg();
    //    QtConcurrent::run(this, &Sql_MCRecorder::SL_updateAlarmAndSendMsg);
}

//********************* 内存写入、查询函数 **********************
void Sql_MCRecorder::cpp_setRecordVal(int addr, int data)
{
    if(addr>=0x63 && addr<=0xD3)
        m_constantRecorder.replace(addr-0x63, data);
    else if(addr>=0x4101 && addr<=0x41EC)
        m_regulatorRecorderA.replace(addr-0x4101, data);
    else if(addr>=0x5101 && addr<=0x51EC)
        m_regulatorRecorderB.replace(addr-0x5101, data);
    else if(addr>=0x48f0 && addr<=0x48f5)
        m_regulatorRecorderTime.replace(addr-0x48f0, data);
}

void Sql_MCRecorder::cpp_modbusRecFinish(QVector<quint16> t_vecQuint16)
{
#ifdef _SQL_DEBUG_PRINT_
    struct timeval tpstart, tpend;
    gettimeofday(&tpstart,NULL);
#endif
    //1-校验数据量是否正确
    if(t_vecQuint16.at(1)!=t_vecQuint16.size()-2)
    {
#ifdef _CPP_DEBUG_PRINT_
        qDebug() << t_vecQuint16.at(1) << t_vecQuint16.size()-2
                 << "数据量不正确,数据起始地址：0x"
                 << QString::number(t_vecQuint16.at(0),16);
#endif
        return;
    }
    //2.1-计算总数
    int t_size = t_vecQuint16.at(1);
    //2.2-计算起始寄存器
    int t_start = t_vecQuint16.at(0);
    //2.3-计算终止寄存器
    int t_end = t_start+t_size-1;
    for(int i=0; i<t_size; i++)
        cpp_setRecordVal(t_start+i, t_vecQuint16.at(i+2));
    //3-到0xC2时,发送信号
    if(t_end>=0xC2 || t_end<=0xD3) m_flagConstantRecorder = true;

#ifdef _SQL_DEBUG_PRINT_
    gettimeofday(&tpend,NULL);
    qDebug() << "write m_recorder,寄存器的数据->内存 use time:" << (tpend.tv_sec-tpstart.tv_sec) * 1000000 + (tpend.tv_usec - tpstart.tv_usec);
#endif
    //4-到0xC2时，更新录波数据库
    if(t_end>=0xC2 || t_end<=0xD3)
        SL_insertFRecorderSQL();
    //        QtConcurrent::run(this, &Sql_MCRecorder::SL_insertFRecorderSQL);
    //5-对时
    if(t_start<0x48F1 && t_end>0x48f4) cpp_setSystemTime();
}

//********************* 槽函数 **********************
void Sql_MCRecorder::SL_updateAlarmAndSendMsg()
{
    int t_pre = qml_queryTableItemNum("alarm_now");
    int t_add = qml_updateAlarmAndRetNum();
    int t_new = qml_queryTableItemNum("alarm_now");
//    sn_sqlAlarmWriteFinish(t_pre, t_add, t_new);
}

void Sql_MCRecorder::SL_insertFRecorderSQL()
{
    //1.1-获取现在时间
    QDateTime current_date_time =QDateTime::currentDateTime();
    QString current_date =current_date_time.toString("yyyy-MM-dd");
    QString current_time =current_date_time.toString("hh:mm:ss.zzz");

    //2-判断T录波功能是否启动
    /*static int s_counter=0;
    if(m_recordTWave==0) s_counter=0;
    else s_counter++;
    if(s_counter>10*m_recordTWave){
        s_counter=0;
        //2.1-风温信息获取
        QString t_str2 = QString("insert into trecorder (date, time, N1T1, N1T2, N2T1, N2T2, N3T1, N3T2) values('%1','%2'").arg(current_time).arg(current_date);
        t_str2 = t_str2+","+QString::number(qml_getRecordVal_bystr_toint16("1#功率柜1PT风温"));
        t_str2 = t_str2+","+QString::number(qml_getRecordVal_bystr_toint16("1#功率柜2PT风温"));
        t_str2 = t_str2+","+QString::number(qml_getRecordVal_bystr_toint16("2#功率柜1PT风温"));
        t_str2 = t_str2+","+QString::number(qml_getRecordVal_bystr_toint16("2#功率柜2PT风温"));
        t_str2 = t_str2+","+QString::number(qml_getRecordVal_bystr_toint16("3#功率柜1PT风温"));
        t_str2 = t_str2+","+QString::number(qml_getRecordVal_bystr_toint16("3#功率柜2PT风温"));
        t_str2 = t_str2+")";
        qDebug() << t_str2;

        //2.2-执行sql语句,并将结果集保存到model
        m_dataTRecorderMutex.lock();
        m_dataTRecordingQueue.enqueue(t_str2);
        m_dataTRecorderMutex.unlock();
    }*/

    //3-判断F录波功能是否启动
    if(m_recordWave==1)
    {
        m_dataFIntQueue.clear();
        return;
    }

    struct _dataFIntStruct t_fIntStruct;
    t_fIntStruct.dateTime.setDate(current_date_time.date());
    t_fIntStruct.dateTime.setTime(current_date_time.time());

    //3.1.1-A套信息获取
//    int t_int[11]={0};
    t_fIntStruct.dataA[0] = qml_getRecordVal_bystr_toint16("A套机端电压");
    t_fIntStruct.dataA[1] = qml_getRecordVal_bystr_toint16("A套机端电流");
    t_fIntStruct.dataA[2] = qml_getRecordVal_bystr_toint16("A套励磁电流");
    t_fIntStruct.dataA[3] = qml_getRecordVal_bystr_toint16("A套同步电压");
    t_fIntStruct.dataA[4] = qml_getRecordVal_bystr_toint16("A套自动给定");
    t_fIntStruct.dataA[5] = qml_getRecordVal_bystr_toint16("A套手动给定");
    t_fIntStruct.dataA[6] = qml_getRecordVal_bystr_toint16("A套控制信号");
    t_fIntStruct.dataA[7] = qml_getRecordVal_bystr_toint16("A套有功功率");
    t_fIntStruct.dataA[8] = qml_getRecordVal_bystr_toint16("A套无功功率");
    t_fIntStruct.dataA[9] = qml_getRecordVal_bystr_toint16("A套电压频率");
    t_fIntStruct.dataA[10] = qml_getRecordVal_bystr_toint16("A套系统电压");

    //3.2.1-B套信息获取
    t_fIntStruct.dataB[0] = qml_getRecordVal_bystr_toint16("B套机端电压");
    t_fIntStruct.dataB[1] = qml_getRecordVal_bystr_toint16("B套机端电流");
    t_fIntStruct.dataB[2] = qml_getRecordVal_bystr_toint16("B套励磁电流");
    t_fIntStruct.dataB[3] = qml_getRecordVal_bystr_toint16("B套同步电压");
    t_fIntStruct.dataB[4] = qml_getRecordVal_bystr_toint16("B套自动给定");
    t_fIntStruct.dataB[5] = qml_getRecordVal_bystr_toint16("B套手动给定");
    t_fIntStruct.dataB[6] = qml_getRecordVal_bystr_toint16("B套控制信号");
    t_fIntStruct.dataB[7] = qml_getRecordVal_bystr_toint16("B套有功功率");
    t_fIntStruct.dataB[8] = qml_getRecordVal_bystr_toint16("B套无功功率");
    t_fIntStruct.dataB[9] = qml_getRecordVal_bystr_toint16("B套电压频率");
    t_fIntStruct.dataB[10] = qml_getRecordVal_bystr_toint16("B套系统电压");

    //4.1-嵌入队列
    m_dataFIntQueue.enqueue(t_fIntStruct);

    //4.2-判断是否报警录波状态
    if(m_dataFEnableFlag)
    {
        //4.3-判断是否结束并置位写入标志
        //闭锁尤为重要，能够保证并发的时候先获得锁才能判断m_dataFCounter是否>目标值
        if((++m_dataFCounter)>_FACTOR_RECORDER_NUMSIZE_)
        {
            m_dataFEnableFlag = false;
            m_dataFCounter = 0;
            QQueue<struct _dataFIntStruct> t_queueBak;
//            m_dataFOptMutex.lock();
//            m_dataFIntQueueBak.clear();
            foreach(struct _dataFIntStruct tt, m_dataFIntQueue)
            {
                t_queueBak.enqueue(tt);
            }
//            m_dataFOptMutex.unlock();
//            m_dataFWriteFlag = true;
            QtConcurrent::run(this, &Sql_MCRecorder::cpp_writeDataFToDb, t_queueBak);
//            cpp_writeDataFToDb(t_queueBak);
        }
    }
    else{
        //4.4-无报警状态下限制住最高2000个数据
        //报警状态下不闭锁，因为新警报到来时会刷新m_dataFCounter=0
        //导致最终数据量可能大于4000个
        while(m_dataFIntQueue.size()>_FACTOR_RECORDER_NUMSIZE_)
            m_dataFIntQueue.dequeue();
    }
}

void Sql_MCRecorder::run()
{
    //建立和sqlite数据的连接
    QSqlDatabase t_db = QSqlDatabase::addDatabase("QSQLITE",QString("excfrecorder_write"));
    while(1){
        //1-模拟量参数录波，100ms一次
        m_dataFOptMutex.lock();
        if(m_dataFWriteFlag)
        {
            m_dataFWriteFlag=false;

            QDir dir;
            if (!dir.exists("../history"))
                qDebug() << "目录../history不存在，尝试创建，是否成功" << dir.mkpath("../history");

            //设置数据库文件的名字
            t_db.setDatabaseName(QString("../history/EXC_FACTOR_RECORDER_%1.db")
                                 .arg(m_dataFIntQueueBak.front().dateTime.toString("yy-MM-dd_hh:mm:ss-zzz")));
            if(!t_db.open()){m_dataFOptMutex.unlock();continue;}

            QSqlQuery query(t_db);

            QString t_str = QString("CREATE TABLE \"frecorder\" (\
                    \"time\"	TIME,\
                    \"date\"	DATE,\
                    \"channal\"	CHAR,\
                    \"ug\"	INT DEFAULT 0,\
                    \"ig\"	INT DEFAULT 0,\
                    \"il\"	INT DEFAULT 0,\
                    \"usyn\"	INT DEFAULT 0,\
                    \"ugd\"	INT DEFAULT 0,\
                    \"igd\"	INT DEFAULT 0,\
                    \"uk\"	INT DEFAULT 0,\
                    \"p\"	INT DEFAULT 0,\
                    \"q\"	INT DEFAULT 0,\
                    \"f\"	INT DEFAULT 0,\
                    \"us\"	INT DEFAULT 0\
                    );");
            bool t_err = query.exec(t_str);
#ifdef _SQL_DEBUG_PRINT_
            if(t_err==false)
                qDebug() << "插入数据库EXC_FACTOR_RECORDER 表 frecorder SQL语句:" << t_str
                         << "SQL错误:表达式错误";
            else
                qDebug() << "插入数据库EXC_MC_RECORDER 表recorder SQL语句:" << t_str
                         << "写入成功";
#endif

            while (m_dataFIntQueueBak.size()!=0) {
                struct _dataFIntStruct tt = m_dataFIntQueueBak.dequeue();
                //A通道
                t_str = QString("insert into frecorder (time,date,channal,ug,ig,il,usyn,ugd,igd,uk,p,q,f,us) values('%1','%2','A'")
                        .arg(tt.dateTime.toString("hh:mm:ss.zzz")).arg(tt.dateTime.toString("yyyy-MM-dd"));
                for(int i=0; i<11; i++)
                    t_str = t_str + "," + QString::number(tt.dataA[i]);
                t_str = t_str+")";

                t_err = query.exec(t_str);
#ifdef _SQL_DEBUG_PRINT_
                if(t_err==false)
                    qDebug() << "插入数据库EXC_FACTOR_RECORDER 表 frecorder SQL语句:" << t_str
                             << "SQL错误:表达式错误";
                else
                    qDebug() << "插入数据库EXC_MC_RECORDER 表recorder SQL语句:" << t_str
                             << "写入成功";
#endif

                //B通道
                t_str = QString("insert into frecorder (time,date,channal,ug,ig,il,usyn,ugd,igd,uk,p,q,f,us) values('%1','%2','B'")
                        .arg(tt.dateTime.toString("hh:mm:ss.zzz")).arg(tt.dateTime.toString("yyyy-MM-dd"));
                for(int i=0; i<11; i++)
                    t_str = t_str + "," + QString::number(tt.dataB[i]);
                t_str = t_str+")";

                t_err = query.exec(t_str);
#ifdef _SQL_DEBUG_PRINT_
                if(t_err==false)
                    qDebug() << "插入数据库EXC_FACTOR_RECORDER 表 frecorder SQL语句:" << t_str
                             << "SQL错误:表达式错误";
                else
                    qDebug() << "插入数据库EXC_MC_RECORDER 表recorder SQL语句:" << t_str
                             << "写入成功";
#endif
            }
            t_db.close();
//            t_db.removeDatabase(QString("excfrecorder_write"));
        }

        m_dataFOptMutex.unlock();
        msleep(100);


        //2-温度录波,2s一次
        /*t_counter++;
        if(t_counter>20){
            t_counter=0;
            m_dataTRecorderMutex.lock();
            if(m_dataTRecordingQueue.isEmpty()==false)
            {
                QString t_str = m_dataTRecordingQueue.dequeue();
                m_dataTRecorderMutex.unlock();
                QSqlQuery query(m_fdb);
                if(query.exec(t_str)==false){
#ifdef _SQL_DEBUG_PRINT_
                    qDebug() << "插入数据库EXC_FACTOR_RECORDER 表 frecorder SQL语句:" << t_str
                             << "SQL错误:表达式错误";
#endif
                }
                else{
#ifdef _SQL_DEBUG_PRINT_
                    qDebug() << "插入数据库EXC_MC_RECORDER 表recorder SQL语句:" << t_str
                             << "写入成功";
#endif
                }
            }
            else m_dataTRecorderMutex.unlock();
        }//*/
    }
}

bool Sql_MCRecorder::cpp_writeDataFToDb(QQueue<struct _dataFIntStruct> i_queueBak)
{
    QDir dir;
    if (!dir.exists("../wave_record"))
        qDebug() << "目录../wave_record不存在，尝试创建，是否成功" << dir.mkpath("../wave_record");

    //建立和sqlite数据的连接
    static QSqlDatabase t_db = QSqlDatabase::addDatabase("QSQLITE",QString("excfre"));

    //设置数据库文件的名字
    t_db.setDatabaseName(QString("../wave_record/EXC_FACTOR_RECORDER_%1.db")
                         .arg(i_queueBak.front().dateTime.toString("yy-MM-dd_hh:mm:ss-zzz")));

    if(!t_db.open())return false;

    QSqlQuery query(t_db);

    QString t_str = QString("CREATE TABLE \"frecorder\" (\
                            \"time\"	TIME,\
                            \"date\"	DATE,\
                            \"channal\"	CHAR,\
                            \"ug\"	INT DEFAULT 0,\
                            \"ig\"	INT DEFAULT 0,\
                            \"il\"	INT DEFAULT 0,\
                            \"usyn\"	INT DEFAULT 0,\
                            \"ugd\"	INT DEFAULT 0,\
                            \"igd\"	INT DEFAULT 0,\
                            \"uk\"	INT DEFAULT 0,\
                            \"p\"	INT DEFAULT 0,\
                            \"q\"	INT DEFAULT 0,\
                            \"f\"	INT DEFAULT 0,\
                            \"us\"	INT DEFAULT 0\
                            );");
    bool t_err = query.exec(t_str);
#ifdef _SQL_DEBUG_PRINT_
    if(t_err==false)
        qDebug() << "插入数据库EXC_FACTOR_RECORDER 表 frecorder SQL语句:" << t_str
                 << "SQL错误:表达式错误";
    else
        qDebug() << "插入数据库EXC_MC_RECORDER 表recorder SQL语句:" << t_str
                 << "写入成功";
#endif

    while (i_queueBak.size()!=0) {
        struct _dataFIntStruct tt = i_queueBak.dequeue();
        //A通道
        t_str = QString("insert into frecorder (time,date,channal,ug,ig,il,usyn,ugd,igd,uk,p,q,f,us) values('%1','%2','A'")
                .arg(tt.dateTime.toString("hh:mm:ss.zzz")).arg(tt.dateTime.toString("yyyy-MM-dd"));
        for(int i=0; i<11; i++)
            t_str = t_str + "," + QString::number(tt.dataA[i]);
        t_str = t_str+")";

        t_err = query.exec(t_str);
#ifdef _SQL_DEBUG_PRINT_
        if(t_err==false)
            qDebug() << "插入数据库EXC_FACTOR_RECORDER 表 frecorder SQL语句:" << t_str
                     << "SQL错误:表达式错误";
        else
            qDebug() << "插入数据库EXC_MC_RECORDER 表recorder SQL语句:" << t_str
                     << "写入成功";
#endif

        //B通道
        t_str = QString("insert into frecorder (time,date,channal,ug,ig,il,usyn,ugd,igd,uk,p,q,f,us) values('%1','%2','B'")
                .arg(tt.dateTime.toString("hh:mm:ss.zzz")).arg(tt.dateTime.toString("yyyy-MM-dd"));
        for(int i=0; i<11; i++)
            t_str = t_str + "," + QString::number(tt.dataB[i]);
        t_str = t_str+")";

        t_err = query.exec(t_str);
#ifdef _SQL_DEBUG_PRINT_
        if(t_err==false)
            qDebug() << "插入数据库EXC_FACTOR_RECORDER 表 frecorder SQL语句:" << t_str
                     << "SQL错误:表达式错误";
        else
            qDebug() << "插入数据库EXC_MC_RECORDER 表recorder SQL语句:" << t_str
                     << "写入成功";
#endif
    }
    t_db.close();

//    QSqlDatabase::removeDatabase(QString("excfre"));
    return true;
}

